; Assign Static IP Address
; This macro allows you to assign a static IP address to the currently connected network
; For Ethernet: assigns static IP to Ethernet interface
; For WiFi Client: assigns static IP to WiFi network

; Step 1: Check that machine is connected to a network
if network.interfaces[1].actualIP == "192.168.0.1"
    abort "Error: Cannot assign static IP in Access Point mode. Please connect via Ethernet or WiFi Client mode first."

; Step 2: Detect current network type and get current IP
var networkType = "NONE"
var currentIP = "0.0.0.0"
var subnet = "255.255.255.0"
var gateway = "0.0.0.0"

if network.interfaces[0].actualIP != "0.0.0.0"
    set var.networkType = "ETHERNET"
    set var.currentIP = network.interfaces[0].actualIP
    if network.interfaces[0].subnet != "0.0.0.0"
        set var.subnet = network.interfaces[0].subnet
    if network.interfaces[0].gateway != "0.0.0.0"
        set var.gateway = network.interfaces[0].gateway
elif network.interfaces[1].actualIP != "0.0.0.0" && network.interfaces[1].actualIP != "192.168.0.1"
    set var.networkType = "WIFI"
    set var.currentIP = network.interfaces[1].actualIP
    if network.interfaces[1].subnet != "0.0.0.0"
        set var.subnet = network.interfaces[1].subnet
    if network.interfaces[1].gateway != "0.0.0.0"
        set var.gateway = network.interfaces[1].gateway
else
    abort "Error: No active network connection found. Please connect to a network first."

; Step 3: Show information about current connection and IP configuration options
var infoMsg1 = "Current Connection: " ^ var.networkType ^ "<br>"
var infoMsg2 = "Current IP Address: " ^ var.currentIP ^ "<br>"
var infoMsg3 = "Assign a static IP address to this connection.<br>"
var infoMsg4 = "The current IP address will be saved, or you can specify a different one."
M291 R"Static IP Assignment" P{var.infoMsg1 ^ var.infoMsg2 ^ var.infoMsg3 ^ var.infoMsg4} S4 K{"Use Current IP","Use Custom IP","Cancel"} F0

if input == 2
    abort "Script canceled by user"

; Step 4: Get IP address (either current or custom)
var targetIP = var.currentIP

if input == 1
    ; User chose custom IP
    var warnMsg1 = "⚠️ Important: Enter a valid IP address for your network.<br>"
    var warnMsg2 = "If there is an IP conflict or invalid configuration,<br>"
    var warnMsg3 = "the machine may not be able to connect to the network.<br>"
    var warnMsg4 = "Proceed at your own risk."
    M291 R"Custom IP Warning" P{var.warnMsg1 ^ var.warnMsg2 ^ var.warnMsg3 ^ var.warnMsg4} S3
    
    M291 S7 H15 R"Enter Static IP Address" P"Example: 192.168.1.100" F{var.currentIP}
    set var.targetIP = input

; Step 5: Test or Skip Test option
var testMsg1 = "IP Address: " ^ var.targetIP ^ "<br>"
var testMsg2 = "Subnet: " ^ var.subnet ^ "<br>"
var testMsg3 = "Gateway: " ^ var.gateway ^ "<br>"
var testMsg4 = "Test the configuration before saving, or skip test and save directly."
M291 R"Static IP Configuration" P{var.testMsg1 ^ var.testMsg2 ^ var.testMsg3 ^ var.testMsg4} S4 K{"Test Configuration","Skip Test & Save","Cancel"} F0

if input == 2
    abort "Script canceled by user"

if input == 1
    ; User chose to skip test and save directly
    if var.networkType == "ETHERNET"
        echo >"0:/sys/user/actions/NetworkMode.g" "M552 I0 S1 P" ^ var.targetIP
        if var.subnet != "0.0.0.0"
            echo >>"0:/sys/user/actions/NetworkMode.g" "M553 P" ^ var.subnet
        if var.gateway != "0.0.0.0"
            echo >>"0:/sys/user/actions/NetworkMode.g" "M554 P" ^ var.gateway
        M291 S2 R"Configuration Saved" P{"Ethernet static IP saved: " ^ var.targetIP ^ "<br>Configuration will be active after restart."}
    elif var.networkType == "WIFI"
        ; Save SSID before any operations
        var wifiSSID = network.interfaces[1].ssid
        
        ; For WiFi, need to get password to reconfigure network with static IP
        M291 S7 H63 R{"WiFi Password for " ^ var.wifiSSID} P"Enter WiFi password (case sensitive)"
        var wifiPass = input
        
        ; Save WiFi configuration with static IP
        echo >"0:/sys/user/actions/WiFiPass.g" "M587 S""" ^ var.wifiSSID ^ """ P""" ^ var.wifiPass ^ """ I" ^ var.targetIP
        echo >"0:/sys/user/actions/NetworkMode.g" "M552 I1 S1 ; Enable WiFi Client Mode"
        M291 S2 R"Configuration Saved" P{"WiFi static IP saved: " ^ var.targetIP ^ "<br>Configuration will be active after restart."}
    M99

; User chose to test configuration (input == 0)
var testingMsg1 = "You will lose connection momentarily.<br>"
var testingMsg2 = "Machine will test the static IP configuration.<br>"
var testingMsg3 = "🟡 YELLOW - Testing<br>🟢 GREEN - Success<br>🔴 RED - Failed"
M291 R"Testing Static IP" P{var.testingMsg1 ^ var.testingMsg2 ^ var.testingMsg3} S4 K{"Begin Test","Cancel"} F0

if input == 1
    abort "Test canceled by user"

M98 P"0:/sys/led/pause.g"  ; Yellow LED - testing

; Create temp network configuration file
if var.subnet != "0.0.0.0"
    echo >"0:/sys/temp-network.g" "M553 P" ^ var.subnet
else
    echo >"0:/sys/temp-network.g" "; No subnet specified"
if var.gateway != "0.0.0.0"
    echo >>"0:/sys/temp-network.g" "M554 P" ^ var.gateway
echo >>"0:/sys/temp-network.g" "M552 P" ^ var.targetIP ^ " I0 S1"

; Step 6: Apply configuration and test
if var.networkType == "ETHERNET"
    ; Turn off interfaces
    M552 I1 S-1
    M552 I0 S0
    G4 S2
    
    ; Apply Ethernet configuration
    M98 P"0:/sys/temp-network.g"
    G4 S5
    
    ; Wait for connection with target IP
    while network.interfaces[0].actualIP != var.targetIP && iterations < 20
        G4 S1
    
    ; Check result
    if network.interfaces[0].actualIP == var.targetIP
        ; Success
        M98 P"0:/sys/led/end.g"  ; Green LED
        
        ; Save configuration
        echo >"0:/sys/user/actions/NetworkMode.g" "M552 I0 S1 P" ^ var.targetIP
        if var.subnet != "0.0.0.0"
            echo >>"0:/sys/user/actions/NetworkMode.g" "M553 P" ^ var.subnet
        if var.gateway != "0.0.0.0"
            echo >>"0:/sys/user/actions/NetworkMode.g" "M554 P" ^ var.gateway
        
        var successMsg1 = "Static IP Configuration Successful<br>"
        var successMsg2 = "IP Address: " ^ var.targetIP ^ "<br>"
        var successMsg3 = "Configuration saved. This IP will remain active after restart."
        M291 S2 R"Success" P{var.successMsg1 ^ var.successMsg2 ^ var.successMsg3}
        
        M98 P"0:/sys/led/resetstatus.g"
        M471 P"0:/sys/temp-network.g"  ; Clean up temp file
        M99
    else
        ; Failed
        M98 P"0:/sys/led/fault.g"  ; Red LED
        
        ; Restore original connection - recreate temp file with original IP
        M552 I0 S0
        G4 S2
        if var.subnet != "0.0.0.0"
            echo >"0:/sys/temp-network.g" "M553 P" ^ var.subnet
        else
            echo >"0:/sys/temp-network.g" "; No subnet specified"
        if var.gateway != "0.0.0.0"
            echo >>"0:/sys/temp-network.g" "M554 P" ^ var.gateway
        echo >>"0:/sys/temp-network.g" "M552 P" ^ var.currentIP ^ " I0 S1"
        M98 P"0:/sys/temp-network.g"
        
        var failMsg1 = "Static IP test failed. Unable to connect with IP: " ^ var.targetIP
        var failMsg2 = "<br>Your router is managing IP addresses and is not accepting the static IP request."
        var failMsg3 = "<br>Please check your router settings or contact your network administrator."
        var failMsg4 = "<br>Restored original IP: " ^ var.currentIP
        M291 S2 R"Test Failed" P{var.failMsg1 ^ var.failMsg2 ^ var.failMsg3 ^ var.failMsg4}
        M98 P"0:/sys/led/resetstatus.g"
        M471 P"0:/sys/temp-network.g"  ; Clean up temp file

elif var.networkType == "WIFI"
    ; Save SSID before turning off WiFi (it becomes unavailable after)
    var wifiSSID = network.interfaces[1].ssid
    
    ; Get WiFi password for reconfiguration
    M291 S7 H63 R{"WiFi Password for " ^ var.wifiSSID} P"Enter WiFi password (case sensitive)"
    var wifiPass = input
    
    ; Turn off interfaces
    M552 I1 S-1
    G4 S2
    M552 I0 S0
    G4 S2
    
    ; Configure WiFi with static IP
    M552 I1 S0
    G4 S5
    M588 S"*"
    G4 S5
    M587 S{var.wifiSSID} P{var.wifiPass} I{var.targetIP}
    
    ; Store result in a variable before comparison
    var m587result = result
    G4 S5
    
    ; If M587 failed, try again after longer wait (result 2 can mean module not ready)
    if var.m587result != 0
            G4 S5
            M587 S{var.wifiSSID} P{var.wifiPass} I{var.targetIP}
            var m587retryResult = result
            G4 S5
            
            ; If still failing, restore network WITHOUT static IP
            if var.m587retryResult != 0
                    M98 P"0:/sys/led/fault.g"
                    
                    ; Clear networks again
                    M588 S"*"
                    G4 S5
                    
                    ; Add network WITHOUT static IP (DHCP mode)
                    M587 S{var.wifiSSID} P{var.wifiPass}
                    G4 S5
                    
                    ; Enable WiFi
                    M552 I1 S1
                    G4 S10
                    
                    ; Build error message
                    var errorMsg = "Failed to configure static IP after 2 attempts."
                    set var.errorMsg = var.errorMsg ^ "<br>Your network has been restored in DHCP mode."
                    set var.errorMsg = var.errorMsg ^ "<br>Your router is managing IP addresses and is not accepting the static IP request."
                    set var.errorMsg = var.errorMsg ^ "<br>Please check your router settings or contact your network administrator."
                    M291 S2 R"WiFi Static IP Failed" P{var.errorMsg}
                    M98 P"0:/sys/led/resetstatus.g"
                    abort "M587 static IP failed, restored DHCP mode"
    
    G4 S5
    
    ; Enable WiFi client mode
    M552 I1 S1
    G4 S3
    
    ; Wait for connection with target IP
    var iterations = 0
    while (network.interfaces[1].actualIP == "0.0.0.0" || network.interfaces[1].actualIP == "192.168.0.1") && var.iterations < 30
        set var.iterations = var.iterations + 1
        G4 S1
    
    ; Check result - normalize strings before comparison
    var actualIP = network.interfaces[1].actualIP
    var actualIPStr = "" ^ var.actualIP
    var targetIPStr = "" ^ var.targetIP
    
    ; Compare IPs - use != with else for success
    if var.actualIPStr != var.targetIPStr
            ; Failed - IPs don't match
            M98 P"0:/sys/led/fault.g"  ; Red LED
            
            ; Restore original WiFi connection
            M552 I1 S0
            G4 S5
            M588 S"*"
            G4 S3
            M587 S{var.wifiSSID} P{var.wifiPass}
            G4 S3
            M552 I1 S1
            G4 S5
            
            set var.iterations = 0
            while (network.interfaces[1].actualIP == "0.0.0.0" || network.interfaces[1].actualIP == "192.168.0.1") && var.iterations < 30
                    set var.iterations = var.iterations + 1
                    G4 S3
            
            M291 S2 R"Test Failed" P{"Static IP test failed.<br>Unable to connect with IP: " ^ var.targetIP ^ "<br>Restored original connection."}
            M98 P"0:/sys/led/resetstatus.g"
    else
            ; Success - IPs match!
            M98 P"0:/sys/led/end.g"  ; Green LED
            
            ; Save configuration
            echo >"0:/sys/user/actions/WiFiPass.g" "M587 S""" ^ var.wifiSSID ^ """ P""" ^ var.wifiPass ^ """ I" ^ var.targetIP
            echo >"0:/sys/user/actions/NetworkMode.g" "M552 I1 S1 ; Enable WiFi Client Mode"
            
            var successMsg1 = "Static IP Configuration Successful<br>"
            var successMsg2 = "IP Address: " ^ var.targetIP ^ "<br>"
            var successMsg3 = "Configuration saved. This IP will remain active after restart."
            M291 S2 R"Success" P{var.successMsg1 ^ var.successMsg2 ^ var.successMsg3}
            
            M98 P"0:/sys/led/resetstatus.g"
            M99